package com.tho.ccolor;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.util.Log;

public class ColorChanger {
	private static String TAG = "Color::Changer";
	private static int MAX_PIXELS = 200*200;
//	private float[] mH;
//	private float[] mS;
//	private float[] mV;
	private Bitmap mBitmap;
	private int[] mRgb;
	private boolean[] mRegion;
	//private boolean[] mReg;
	private int mRows;
	private int mCols;
	private float mHLowerBound = 0;
	private float mHUpperBound = 0;
	private float mSLowerBound = 0;
	private float mSUpperBound = 0;
	private float mVLowerBound = 0;
	private float mVUpperBound = 0;
	
	private float mThreshold = 0.2f;
	private ColorHSV mSeedColor;
	private ColorHSV mMeanColor;
	private List<Point> mOrient = new ArrayList<Point>();

	public ColorChanger(Bitmap bitmap){
		mRows = bitmap.getHeight();
		mCols = bitmap.getWidth();
//		mH = new float[mRows*mCols];
//		mS = new float[mRows*mCols];
//		mV = new float[mRows*mCols];
		mRgb = new int[mRows*mCols];		
		mRegion = new boolean[mRows*mCols];
		//convert bitmap to array
		mBitmap = bitmap.copy(bitmap.getConfig(), true);
		mBitmap.getPixels(mRgb, 0, mCols, 0, 0, mCols, mRows);
//		//convert bitmap to hsv
//		float[] pixelHSV = new float[3];
//		int index = 0;
//		for(int y = 0; y < mRows; y++){
//			for(int x = 0; x < mCols; x++){
//				Color.colorToHSV(mRgb[index], pixelHSV);
//				mH[index] = pixelHSV[0];
//				mS[index] = pixelHSV[1];
//				mV[index] = pixelHSV[2];
//				index++;
//			}
//		}
		//mBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
		//mBitmap = bitmap.copy(bitmap.getConfig(), true);
		//mBitmap = bitmap;
		mOrient.add(new Point(0,1));
		mOrient.add(new Point(1,0));
		mOrient.add(new Point(-1,0));
		mOrient.add(new Point(0,-1));
		mOrient.add(new Point(-1,-1));
		mOrient.add(new Point(1,1));
		mOrient.add(new Point(-1,1));
		mOrient.add(new Point(1,-1));
	}
	public void replaceColor(Bitmap bitmap, Point seed, int newColor){
		
	}
	public Bitmap replaceColor(Point seed, ColorHSV newColor){
long t1 = System.currentTimeMillis();
		mSeedColor = getColorHSV(seed);
		//implement of algorithm seeded region growing
		boolean cont = true;
		int area = mCols * mRows;
		area = (area > MAX_PIXELS) ? MAX_PIXELS : area;
		int size = 0;
		PointHSV currentPixel = new PointHSV(seed.x, seed.y, mSeedColor);
		mMeanColor = mSeedColor;
		//List<PointHSV> pointsHsv = new LinkedList<PointHSV>();
		TreeSet<PointHSV> pointHSVs = new TreeSet<PointHSV>();		
		mRegion[seed.y*mCols + seed.x] = true;
 		while (size < area){
//Log.i(TAG, "Position curr:" + currentPixel.y*mCols + currentPixel.x); 			
			for(Point orient: mOrient){
				//Point tempPixel = new Point (currentPixel.x + orient.x, currentPixel.y + orient.y);
				//pixel is in image and not already selected before
				int newX = currentPixel.x + orient.x;
				int newY = currentPixel.y + orient.y;
				int position = newY*mCols + newX;
//Log.i(TAG, "Position:" + position);				
				if(newX >= 0 && newX < mCols && newY >=0 && newY < mRows && mRegion[position] == false){
					float[] pixelHSV = new float[3];
					Color.colorToHSV(mRgb[position], pixelHSV);
										
					ColorHSV colorHSV = new ColorHSV(pixelHSV[0], pixelHSV[1], pixelHSV[2]);
					float d = colorHSV.distance(mMeanColor);
					//if(d < 3*mThreshold){
//Log.i(TAG, "SSL SIZE BEFORE ADD " + pointHSVs.size());						
//Log.i(TAG, "SSL ADD " + newX + "," + newY);					
						pointHSVs.add(new PointHSV(newX, newY, colorHSV, d));

//Log.i(TAG, "SSL SIZE AFTER ADD " + pointHSVs.size());
					//}
//Log.i(TAG, "" + d);					
					mRegion[position] = true;
				}
			}
//Log.i(TAG, "Size ssl:" + pointHSVs.size());				
			if(pointHSVs.size() == 0 || pointHSVs.first().distance > mThreshold){
				//cont = false;
//Log.i(TAG, "Size:" + size);	
				break;
			}
//			List<Float> distances = new ArrayList<Float>();
//			for(int i = 0; i < pointsHsv.size(); i++){
//				float d = pointsHsv.get(i).getColorHSV().distance(mMeanColor);
//				if(d < 3*mThreshold){
//					distances.add(d);
//				}	
//			}
//			Float minDist = Collections.min(distances);
//			int index = distances.indexOf(minDist);
//			if(minDist > mThreshold){
//				break;
//			}
			//currentPixel = pointHSVs.first();
			currentPixel = pointHSVs.pollFirst();
			size += 1;
			float newH = (mMeanColor.h* size + currentPixel.colorHSV.h)/(size + 1);
			float newS = (mMeanColor.s* size + currentPixel.colorHSV.s)/(size + 1);
			float newV = (mMeanColor.v* size + currentPixel.colorHSV.v)/(size + 1);
			mMeanColor = new ColorHSV(newH, newS, newV);			
			int c = Color.HSVToColor(new float[] {newColor.h, newColor.s, currentPixel.colorHSV.v});
			mRgb[currentPixel.y * mCols + currentPixel.x] = c;	
		}
Log.i("COLOR_CHANGER", "" + (System.currentTimeMillis() - t1));
		Bitmap newBitmap = Bitmap.createBitmap(mRgb, mCols, mRows, mBitmap.getConfig());
		return newBitmap;
	}

//	private float getV(Point p){
//		return mV[p.y*mCols + p.x];
//	}
		
	private void setThresholds(int color){
	}
	private boolean isInImage(Point point){
		return point.x >= 0 && point.x < mCols && point.y >=0 && point.y < mRows;		
	}
	private ColorHSV getColorHSV(Point point){
		return getColorHSV(mBitmap.getPixel(point.x, point.y));
	}
	private ColorHSV getColorHSV(int color){
		float[] pixelHSV = new float[3];
		Color.colorToHSV(color, pixelHSV);
		return new ColorHSV(pixelHSV[0], pixelHSV[1], pixelHSV[2]);
	}
}